# -*- coding: utf-8-*-
import datetime
import re
from openerp import models, SUPERUSER_ID
from openerp.osv import osv, fields, orm
"""
1.在客户信息界面增加客户等级选项，并且增加客户等级字段的修改添加描述等功能，
2.当用户下销售订单时，如果消费额度大于信用余额则能成功确认订单，
订单不能生效。
"""


class express_type(osv.osv):
    """
    新建，添加，修改，快递方式
    """
    _name = 'express.type'
    _rec_name = 'name'
    _columns = {
        'name': fields.char(u'快递方式', size=64, required=True),
        'description': fields.char(u'描述', size=64),
    }


class customer_level(osv.osv):
    """
    新建，添加，修改，客户级
    """
    _name = 'customer.level'
    _rec_name = 'name'
    _columns = {
        'name': fields.char(u'客户级别', size=64, required=True),
        'description': fields.char(u'客户级别描述', size=64),
    }


class res_partner_address(osv.osv):
    _name = 'res.partner.address'

    _rec_name = 'contacts'

    def onchange_province(self, cr, uid, ids, county, city, province, context=None):
        # 为地址填写时方便，当选定省时 ，市区的列表里面只有所选省的
        if province:
            if city:
                city_obj = self.pool.get('all.city').browse(
                    cr, uid, [city], context=context)
                if city_obj[0].province_name.id == province:
                    if county:
                        county_obj = self.pool.get('all.country').browse(
                            cr, uid, [county], context=context)
                        if county_obj.city_name.id == city:
                            return{}
                    return {'domain': {'city_id': [('province_name', '=', province)]}, 'value': {'county_id': ''}}
                else:
                    return {'domain': {'city_id': [('province_name', '=', province)]}, 'value': {'city_id': ''}}
            else:
                return {'domain': {'city_id': [('province_name', '=', province)]}}
        else:
            return {'domain': {'city_id': [], 'county_id': []}, 'value': {'county_id': '', 'city_id': ''}}

    def onchange_country(self, cr, uid, ids, county, city, province, context=None):
        # 选定了一个区县，自动填充其所属的省和市
        if county:
            try:
                county_obj = self.pool.get('all.country').browse(
                    cr, uid, [county], context=context)
                city_obj = self.pool.get('all.city').browse(
                    cr, uid, county_obj[0].city_name.id, context=context)
                return {'domain': {'county_id': [('city_name', '=', city)]}, 'value': {'city_id': county_obj[0].city_name.id, 'province_id': city_obj[0].province_name.id}}
            except Exception, ex:
                raise osv.except_osv(u'错误', u"无法根据所选区县填充省和市")

    def onchange_city(self, cr, uid, ids, county, city, province, context=None):
        # 为地址填写时方便，当选定市时 ，县区的列表里面只有所选市的
        if city:
            city_obj = self.pool.get('all.city').browse(
                cr, uid, [city], context=context)
            province_id = city_obj[0].province_name
            if not province:
                if county:
                    county_obj = self.pool.get('all.country').browse(
                        cr, uid, [county], context=context)
                    if county_obj[0].city_name.id == city:
                        return {'domain': {'county_id': [('city_name', '=', city)]}}
                    return {'value': {'county_id': "", 'province_id': province_id}, 'domain': {'county_id': [('city_name', '=', city)]}}
                return {'value': {'province_id': province_id}, 'domain': {'county_id': [('city_name', '=', city)]}}
            else:
                if county:
                    county_obj = self.pool.get('all.country').browse(
                        cr, uid, [county], context=context)
                    if county_obj.city_name.id == city:
                        if province_id.id != province:
                            return {'domain': {'county_id': [('city_name', '=', city)], 'city_id': [('province_name', '=', province_id.id)]}, 'value': {'province_id': province_id}}
                        return {'domain': {'county_id': [('city_name', '=', city)], 'city_id': [('province_name', '=', province_id.id)]}}
                    else:
                        if province_id.id != province:
                            return {'domain': {'county_id': [('city_name', '=', city)], 'city_id': [('province_name', '=', province_id.id)]}, 'value': {'province_id': province_id.id, 'county_id': ""}}
                        return {'domain': {'county_id': [('city_name', '=', city)], 'city_id': [('province_name', '=', province_id.id)]}, 'value': {'county_id': ""}}
                else:
                    if province_id.id != province:
                        return {'domain': {'county_id': [('city_name', '=', city)], 'city_id': [('province_name', '=', province_id.id)]}, 'value': {'province_id': province_id.id}}
                    return {'domain': {'county_id': [('city_name', '=', city)], 'city_id': [('province_name', '=', province_id.id)]}}
        else:
            return {'domain': {'county_id': []}, 'value': {'county_id': ""}}

    def check_mobile(self, cr, uid, ids, context=None):
        # 检查手机号码是否正确
        for partner_address in self.browse(cr, uid, ids, context=context):
            if partner_address.mobile_number:
                p2 = re.compile('\d{11}')
                if not p2.match(partner_address.mobile_number):
                    return False
            return True

    _columns = {
        'sexual': fields.char(u'性别', size=64),
        'contacts': fields.char(u'联系人', size=64, required=True),
        'phone_number': fields.char(u'电话号', size=64),
        'mobile_number': fields.char(u'手机号', size=64),
        'note': fields.text(u'备注'),
        'department': fields.char(u'部门'),
        'birthday': fields.date(u'生日'),
        'duties': fields.char(u'职务', size=64),
        'email': fields.char(u'邮箱', size=64),
        'QQ': fields.char(u'QQ', size=64),
        'zp_code': fields.char(u'邮编', size=64),
        'province_id': fields.many2one('res.country.state', u'省', domain="[('country_id.name','=','中国')]", required=True),
        'city_id': fields.many2one('all.city', u'市', required=True),
        'county_id': fields.many2one('all.country', u'县', required=True),
        'detail_street': fields.char(u'具体街道地址', size=64, required=True),
        'partner': fields.many2one('res.partner', u'客户', required=True),
    }
    _constraints = [(check_mobile, u'联系人手机号不合规范', ['mobile_number'])]


class res_partner(osv.osv):
    _inherit = 'res.partner'

    def write(self, cr, uid, ids, vals, context=None):
        model_data_obj = self.pool.get('ir.model.data')
        users = self.pool.get('res.users')
        groups = self.pool.get('res.groups')
        if vals.get('customerlevel', False):
            group_account_id = model_data_obj.xmlid_to_res_id(
                cr, SUPERUSER_ID, 'account.group_account_invoice')
            group_account_obj = groups.browse(
                cr, SUPERUSER_ID, group_account_id, context=context)
            user_obj = group_account_obj.users
            self.message_subscribe_users(cr, SUPERUSER_ID, ids, user_ids=[
                                         user.id for user in group_account_obj.users], context=context)
            self.message_post(cr, SUPERUSER_ID, ids, u"客户等级发生变化请及时更新价格表",
                              subtype='mail.mt_comment', context=context)
        for partner_id in ids:
            user_id = users.search(
                cr, SUPERUSER_ID, [('partner_id', '=', partner_id)])
            if user_id:
                # 当已有用户是就执行修改操作
                group_store = model_data_obj.xmlid_to_res_id(
                    cr, SUPERUSER_ID, 'dzx_ext.group_stores')
                group_agent = model_data_obj.xmlid_to_res_id(
                    cr, SUPERUSER_ID, 'dzx_ext.group_agents')
                user = users.browse(cr, SUPERUSER_ID, user_id, context=context)
                if vals.get('is_agents', False):
                    # 给已有客户添加代理权限
                    groups.write(cr, SUPERUSER_ID, group_agent, {
                                 'users': [(4, user.id)]}, context)
                elif (not vals.get('is_agents', True)):
                    # 在管理员取消客户的代理权限
                    groups.write(cr, SUPERUSER_ID, group_agent, {
                                 'users': [(3, user.id)]}, context)
                    # try:
                    #     users.unlink(cr, SUPERUSER_ID,
                    #                  user_id, context=context)
                    # except:
                    #     raise osv.except_osv(u'警告', u"此用户已存在关键操作记录，不能删除该用户")

                if vals.get('is_stores', False):
                    # 给已有客户添加门店权限
                    groups.write(cr, SUPERUSER_ID, group_store, {
                                 'users': [(4, user.id)]}, context)

                elif (not vals.get('is_stores', True)):
                    # 在管理员取消客户的门店权限
                    groups.write(cr, SUPERUSER_ID, group_store, {
                                 'users': [(3, user.id)]}, context)
                    # try:
                    #     users.unlink(cr, SUPERUSER_ID,
                    #                  user_id, context=context)
                    # except:
                    #     raise osv.except_osv(u'警告', u"此用户已存在关键操作记录，不能删除该用户")

                if vals.get('login', False):
                    # 修改客户的登录名
                    users.write(cr, SUPERUSER_ID, user_id[0], {
                                'login': vals.get('login')}, context)
                if vals.get('passwd', False):
                    # 修改客户的登录权限
                    users.write(cr,SUPERUSER_ID,user_id[0],{'password':vals.get('passwd')},context)
                    #raise osv.except_osv(u'警告', u"目前不能替代理商修改密码，请联系管理员让管理员来修改!")
            else:
                # 当不存在用户时先获取login以备后用
                if vals.get('login', False):
                    partner = vals.get('login', False)
                else:
                    partner = (self.browse(cr, SUPERUSER_ID,
                                           ids, context=context))[0].login
                # 判断当是门店或者代理商其中之一勾选时， 就先建立用户。
                if vals.get('is_agents', False) or vals.get('is_stores', False):
                    user_id = self.pool.get('res.users').create(cr, SUPERUSER_ID,
                                                                {'login': partner,
                                                                 'active': True,
                                                                 'partner_id': partner_id,
                                                                 'password': vals['passwd'],
                                                                 'sel_groups_5': False,
                                                                 'in_group_1': True,
                                                                 'lang': 'zh_CN'}, context=context)
                    # 判断新建用户应该被分派到那个组中
                    if vals.get('is_stores', False):
                        group_store = model_data_obj.xmlid_to_res_id(
                            cr, 1, 'dzx_ext.group_stores')
                        groups.write(cr, SUPERUSER_ID, group_store, {
                                     'users': [(4, user_id)]}, context)
                    if vals.get('is_agents', False):
                        group_agent = model_data_obj.xmlid_to_res_id(
                            cr, SUPERUSER_ID, 'dzx_ext.group_agents')
                        groups.write(cr, SUPERUSER_ID, group_agent, {
                                     'users': [(4, user_id)]}, context)

        return super(res_partner, self).write(cr, uid, ids, vals, context=context)

    def create(self, cr, uid, vals, context=None):
        groups = self.pool.get('res.groups')
        model_data_obj = self.pool.get('ir.model.data')

        res_partner_id = super(res_partner, self).create(
            cr, uid, vals, context=context)
        # 当勾选代理商或者门店是-新建用户
        if vals.get('is_agents', False) or vals.get('is_stores', False):
            user_id = self.pool.get('res.users').create(cr, 1,
                                                        {'login': vals['login'],
                                                         'active': True,
                                                         'partner_id': res_partner_id,
                                                         'password': vals['passwd'],
                                                         'sel_groups_5': False,
                                                         'in_group_1': True,
                                                         'lang': 'zh_CN'}, context=context)

        if vals.get('is_stores', False):
            group_store = model_data_obj.xmlid_to_res_id(
                cr, SUPERUSER_ID, 'dzx_ext.group_stores')
            groups.write(cr, SUPERUSER_ID, group_store, {
                         'users': [(4, user_id)]}, context)
        if vals.get('is_agents', False):
            group_agent = model_data_obj.xmlid_to_res_id(
                cr, SUPERUSER_ID, 'dzx_ext.group_agents')
            groups.write(cr, SUPERUSER_ID, group_agent, {
                         'users': [(4, user_id)]}, context)
        if vals.get('customerlevel', False):
            group_account_id = model_data_obj.xmlid_to_res_id(
                cr, SUPERUSER_ID, 'account.group_account_invoice')
            group_account_obj = groups.browse(
                cr, uid, group_account_id, context=context)
            user_obj = group_account_obj.users
            self.message_subscribe_users(cr, uid, res_partner_id, user_ids=[
                                         user.id for user in group_account_obj.users], context=context)
            self.message_post(cr, uid, uid, u"客户等级发生变化请及时更新价格表",
                              subtype='mail.mt_comment', context=context)
        return res_partner_id

    def _compute_balance(self, cr, uid, ids, name, arg, context=None):
        res = {}
        for partner in self.browse(cr, 1, ids, context=context):
            # 如果不是公司并且有母公司，则取得母公司的可用信用额度
            if partner.is_company == False and partner.parent_id:
                res[partner.id] = partner.parent_id.credit_limit - \
                    partner.parent_id.credit
            else:
                res[partner.id] = partner.credit_limit - partner.credit
        return res

    def onchange_province(self, cr, uid, ids, county, city, province, context=None):
        # 为地址填写时方便，当选定省时 ，市区的列表里面只有所选省的
        if province:
            if city:
                city_obj = self.pool.get('all.city').browse(
                    cr, uid, [city], context=context)
                if city_obj[0].province_name.id == province:
                    if county:
                        county_obj = self.pool.get('all.country').browse(
                            cr, uid, [county], context=context)
                        if county_obj.city_name.id == city:
                            return{}
                    return {'domain': {'city_id': [('province_name', '=', province)]}, 'value': {'county_id': ''}}
                else:
                    return {'domain': {'city_id': [('province_name', '=', province)]}, 'value': {'city_id': ''}}
            else:
                return {'domain': {'city_id': [('province_name', '=', province)]}}
        else:
            return {'domain': {'city_id': [], 'county_id': []}, 'value': {'county_id': '', 'city_id': ''}}

    def onchange_county(self, cr, uid, ids, county, city, province, context=None):
        # 选定了一个区县，自动填充其所属的省和市
        if county:
            try:
                county_obj = self.pool.get('all.country').browse(
                    cr, uid, [county], context=context)
                city_obj = self.pool.get('all.city').browse(
                    cr, uid, county_obj[0].city_name.id, context=context)
                return {'domain': {'county_id': [('city_name', '=', city)]}, 'value': {'city_id': county_obj[0].city_name.id, 'province_id': city_obj[0].province_name.id}}
            except Exception, ex:
                raise osv.except_osv(u'错误', u"无法根据所选区县填充省和市")

    def onchange_city(self, cr, uid, ids, county, city, province, context=None):
        # 为地址填写时方便，当选定市时 ，县区的列表里面只有所选市的
        if city:
            city_obj = self.pool.get('all.city').browse(
                cr, uid, [city], context=context)
            province_id = city_obj[0].province_name
            if not province:
                if county:
                    county_obj = self.pool.get('all.country').browse(
                        cr, uid, [county], context=context)
                    if county_obj[0].city_name.id == city:
                        return {'domain': {'county_id': [('city_name', '=', city)]}}
                    return {'value': {'county_id': "", 'province_id': province_id}, 'domain': {'county_id': [('city_name', '=', city)]}}
                return {'value': {'province_id': province_id}, 'domain': {'county_id': [('city_name', '=', city)]}}
            else:
                if county:
                    county_obj = self.pool.get('all.country').browse(
                        cr, uid, [county], context=context)
                    if county_obj.city_name.id == city:
                        if province_id.id != province:
                            return {'domain': {'county_id': [('city_name', '=', city)], 'city_id': [('province_name', '=', province_id.id)]}, 'value': {'province_id': province_id}}
                        return {'domain': {'county_id': [('city_name', '=', city)], 'city_id': [('province_name', '=', province_id.id)]}}
                    else:
                        if province_id.id != province:
                            return {'domain': {'county_id': [('city_name', '=', city)], 'city_id': [('province_name', '=', province_id.id)]}, 'value': {'province_id': province_id.id, 'county_id': ""}}
                        return {'domain': {'county_id': [('city_name', '=', city)], 'city_id': [('province_name', '=', province_id.id)]}, 'value': {'county_id': ""}}
                else:
                    if province_id.id != province:
                        return {'domain': {'county_id': [('city_name', '=', city)], 'city_id': [('province_name', '=', province_id.id)]}, 'value': {'province_id': province_id.id}}
                    return {'domain': {'county_id': [('city_name', '=', city)], 'city_id': [('province_name', '=', province_id.id)]}}
        else:
            return {'domain': {'county_id': []}, 'value': {'county_id': ""}}

    def onchange_login(self, cr, uid, ids, is_stores, is_agents, context=None):
        # 门店及代理商用户的默认密码为123456
        if is_stores or is_agents:
            login,psw = False,'123456'
            if ids:
                user_id = self.pool.get('res.users').search(cr,uid,[('partner_id','=',ids[0])],context=context)
                users_row = self.pool.get('res.users').browse(cr,uid,user_id,context=context)
                login = users_row.login
            return {'value': {'passwd': '123456','login':login,'passwd':psw}}


    def onchange_mobile(self, cr, uid, ids, mobile, context=None):
        if mobile:
            p2 = re.compile('^0\d{2,3}\d{7,8}$|^1[358]\d{9}$|^147\d{8}')
            if not p2.match(mobile):
                raise osv.except_osv(u'警告！', u'客户手机号码不合规范!')
            return True

    def _compute_customer_fee(self, cr, uid, ids, name, arg, context=None):
        res = {}
        for partner_obj in self.browse(cr, uid, ids, context=context):
            voucher_ids = self.pool.get("account.voucher").search(
                cr, uid, [('partner_id', '=', partner_obj.id)], context=context)
            if voucher_ids:
                res[partner_obj.id] = sum([voucher_obj.amount for voucher_obj in self.pool.get(
                    'account.voucher').browse(cr, uid, voucher_ids, context=context)])
            else:
                res[partner_obj.id] = 0
        return res
    _columns = {
        'login': fields.char(u'用户登录账号'),
        'is_stores': fields.boolean(u'门店'),
        'is_agents': fields.boolean(u'客户账号'),
        'passwd': fields.char(u'用户登录密码（默认123456）'),
        'balance': fields.function(_compute_balance, string=u'信用余额(信用额度减应收款)', type='float',),
        'customerlevel': fields.many2one('customer.level', u'客户等级', track_visibility='always'),
        'addresses': fields.one2many('res.partner.address', 'partner', u'客户地址', required=True),
        'province_id': fields.many2one('res.country.state', u'省', domain="[('country_id.name','=','中国')]"),
        'city_id': fields.many2one('all.city', u'市'),
        'county_id': fields.many2one('all.country', u'县'),
        'on_duty_people': fields.char(u'负责人'),
        'user_id': fields.many2one('res.users', u'销售员', required=True),
        'short_name': fields.char(string=u'简称', size=64),
        'last_contact_time': fields.datetime(string=u'最后联系时间'),
        'paid_amount': fields.function(_compute_customer_fee, string='已付金额', type='float'),
    }
    _sql_constraints = [
        ('res_name_uniq', 'UNIQUE(name)', u'客户的名字必须唯一!'),
    ]
    _defaults = {
        'is_company': True,
        'user_id': lambda self, cr, uid, context=None: uid
    }


class sale_order(osv.osv):
    """
        1.继承已有的销售订单并添加 客户信用余额 。
        2.并且设定当客户订单消费金额，大于信用余额时 。警告并且不能提交订单。
    """
    _inherit = 'sale.order'

    _rec_name = 'name'

    def check_rebate(self, cr, uid, ids, limit, context=None):
     # 检查优惠金额是否超过设定值(在sale.order.base流程中新增了一个迁移)
        for order in self.browse(cr, uid, ids, context=context):
            total_rebate = 0
            for line in order.order_line:
                if line.price_subtotal < 0:
                    total_rebate += line.price_subtotal
            if total_rebate < limit:
                return False
        return True

    def check_is_return(self, cr, uid, ids, context=None):
        # 同一张订单中产品正负数量不能混用
        sale_order_obj = self.browse(cr, uid, ids, context=context)
        order_lines = sale_order_obj.order_line

        if not sale_order_obj.order_line:
            raise osv.except_osv(u'警告！', u'订单行为空不能确认订单')
        if sale_order_obj.order_line[0].product_uom_qty > 0:
            flag = True
        else:
            flag = False
        for order_line in sale_order_obj.order_line[1:]:
            if order_line.product_uom_qty < 0 and flag:
                raise osv.except_osv(u'警告!', u'同一张订单中产品正负数量不能混用')

            if order_line.product_uom_qty > 0 and not flag:
                raise osv.except_osv(u'警告!', u'同一张订单中产品正负数量不能混用')

        return True

    def action_quotation_send(self, cr, uid, ids, context=None):
        # 重载提交审核（原发送报价单）按钮
        self.check_is_return(cr, uid, ids, context)
        self.check_balance(cr, 1, ids, context)
        self.signal_workflow(cr, 1, ids, 'quotation_sent')
        return True

    def check_balance(self, cr, uid, ids, context=None):
        assert len(
            ids) == 1, 'This option should only be used for a single id at a time.'
        order = self.browse(cr, uid, ids, context=context)[0]
        partner = order.partner_id
        # 应收款合计(负数表示欠客户的或者客户可用于支付订单的额度)
        credit = partner.credit
        # 设定的信用额度
        credit_limit = partner.credit_limit
        # 如果不是公司且有父级公司，则取父级客户公司的应收款和信用额度
        if not partner.is_company and partner.parent_id:
            credit = partner.parent_id.credit
            credit_limit = partner.parent_id.credit_limit
        credit_or_prepaid = u'应收:%s' % credit
        if credit < 0:
            credit_or_prepaid = u'预付:%s' % credit
        if order.amount_total > 0 and partner.balance < order.amount_total:
            raise osv.except_osv(u'警告!', u'客户余额或授信额度不足(信用:%s, %s), 信用余额:%s, 订单金额:%s'
                                 % (credit_limit, credit_or_prepaid, partner.balance, order.amount_total))
        return credit

    def action_button_confirm(self, cr, uid, ids, context=None):
        assert len(
            ids) == 1, 'This option should only be used for a single id at a time.'
        # 如果检查信用余额不足则抛出例外
        self.check_balance(cr, 1, ids, context)
        self.signal_workflow(cr, 1, ids, 'order_confirm')
        return True

    def create_stock_move_in(self, cr, uid, ids, context=None):
         # 根据订单建立入库单
        if isinstance(ids, (int, long)):
            ids = [ids]

        procurement_group_obj = self.pool.get("procurement.group")
        pick_obj = self.pool.get("stock.picking")
        incoming_picking_type_id = self.pool.get('stock.picking.type').search(
            cr, uid, [('code', '=', 'incoming')], context=context)[0]

        # 订单遍历
        for order in self.browse(cr, uid, ids, context=context):
            # 建立需求组
            # values = {
            #     'name': order.name,
            #     'move_type': order.picking_policy or 'direct',
            #     'partner_id': order.partner_id.id or False,
            # }
            values = self._prepare_procurement_group(
                cr, uid, order, context=context)
            if not order.procurement_group_id:
                group_id = procurement_group_obj.create(
                    cr, uid, values, context=context)
                order.write({'procurement_group_id': group_id},
                            context=context)
            else:
                group_id = order.procurement_group_id.id
            # 建立stock.picking
            values = {
                'origin': order.name,
                'company_id': order.company_id and order.company_id.id or False,
                'move_type': order.picking_policy or 'direct',
                'partner_id': order.partner_id.id or False,
                'picking_type_id': incoming_picking_type_id,
                #'group_id': group_id, 自动会从stock.move中取得并存储
            }
            pick_id = pick_obj.create(cr, uid, values, context=context)
            # 建立stock.move
            # picking = pick_obj.browse(cr, uid, pick_id, context=context)
            # picking = pick_obj.browse(cr, uid, pick_id, context=context)
            stock_move_obj = self.pool.get('stock.move')
            for line in order.order_line:
                if line.product_id.type in ['service']:
                    continue
                vals = {
                    'company_id': order.company_id and order.company_id.id or False,
                    'group_id': group_id,
                    'picking_id': pick_id,
                    'picking_type_id': incoming_picking_type_id,
                    'location_id': order.partner_shipping_id.property_stock_supplier.id,
                    'location_dest_id': order.company_id.partner_id.property_stock_customer.id,
                    'name': u'退货:' + (line.name or ''),
                    'product_id': line.product_id.id,
                    'product_uom': line.product_uom.id,
                    'product_uom_qty': abs(line.product_uom_qty),
                    'date': fields.datetime.now(),
                    'state': 'confirmed',
                    'origin': order.name,
                }
                stock_move_obj.create(cr, uid, vals, context=context)

    def action_ship_create(self, cr, uid, ids, context=None):
        # 重载建立出货单函数，实现是否退货单的判断和建立退货入库单
        assert len(ids) == 1, u'只能处理一个订单的建立出货单或退货入库单'
        order = self.browse(cr, uid, ids, context=context)[0]
        if order.order_line[0].product_uom_qty < 0:
            order.write({'is_return': True}, context=context)
            self.create_stock_move_in(cr, uid, ids, context=context)
        else:
            super(sale_order, self).action_ship_create(
                cr, uid, ids, context=context)
        return True

    def _prepare_invoice(self, cr, uid, order, lines, context=None):
        # 重载准备发票函数，负数订单（退货单）需要生成红字发票，改为第一个产品如果是负数则生成红字发票
        invoice_vals = super(sale_order, self)._prepare_invoice(
            cr, uid, order, lines, context=context)
        # if order.amount_total < 0:
        if order.order_line[0].product_uom_qty < 0:
            journal_ids = self.pool.get('account.journal').search(cr, uid,
                                                                  [('type', '=', 'sale_refund'), (
                                                                      'company_id', '=', order.company_id.id)],
                                                                  limit=1)
            invoice_vals.update({
                'type': 'out_refund',
                'journal_id': journal_ids[0]
            })
            obj_invoice_line = self.pool.get('account.invoice.line')
            for inv_line_id in lines:
                inv_line = obj_invoice_line.browse(
                    cr, uid, inv_line_id, context=context)
                inv_line.write({'quantity': 0 - inv_line.quantity,
                                'price_unit': inv_line.price_unit,
                                'price_subtotal': 0 - inv_line.price_subtotal})
        return invoice_vals

    def _get_default_partner_id(self, cr, uid, ids, context=None):
        # 获取代理商的partner_id
        if self.pool.get('res.users').browse(cr, uid, uid, context=context).has_group('dzx_ext.group_agents'):
            return self.pool.get('res.users').browse(cr, uid, uid, context=context).partner_id.id

    def onchange_province(self, cr, uid, ids, county, city, province, context=None):
        # 选择省后，将市约束为属于该省的才显示在下拉框
        if province:
            return {'domain': {'city_id': [('province_name', '=', province)]}}

    def onchange_city(self, cr, uid, ids, county, city, province, context=None):
        # 在选择市的时候，如果没有选择省，则自动填写该市对应的省，县城约束为属于该市的才显示在下拉框
        if not province:
            if city:
                city_obj = self.pool.get('all.city').browse(
                    cr, uid, [city], context=context)
                province_id = city_obj[0].province_name

                return {'value': {'county_id': "", 'province_id': province_id.id, }, 'domain': {'county_id': [('city_name', '=', city)]}}
        if city:
            return {'domain': {'county_id': [('city_name', '=', city)]}}

    def onchange_county(self, cr, uid, ids, county, city, province, context=None):
        # 在选择县的时候将省市自动选择为该县对应的省，市
        if county:
            try:
                county_obj = self.pool.get('all.country').browse(
                    cr, uid, [county], context=context)
                city_obj = self.pool.get('all.city').browse(
                    cr, uid, county_obj[0].city_name.id, context=context)
                return {'value': {'province_id': city_obj[0].province_name.id, 'city_id': county_obj[0].city_name.id}}
            except Exception, ex:
                raise osv.except_osv(u'error', u"出错了")

    def onchange_partner_id(self, cr, uid, ids, part, context=None):
        '''当客户改变时，销售订单的地址随之而改变'''
        val = {}
        ret = super(sale_order, self).onchange_partner_id(
            cr, uid, ids, part, context=context)
        partner = self.pool.get('res.partner').browse(
            cr, uid, part, context=context)
        val = {
            'province_id': partner.province_id.id,
            'city_id': partner.city_id.id,
            'county_id': partner.county_id.id,
            'street': partner.street,
            'zip': partner.zip,
            'phone': partner.phone,
            'mobile': partner.mobile,
            'consignee': partner.on_duty_people,
        }
        ret['value'].update(val)

        return ret

    def onchange_contacts(self, cr, uid, ids, contacts, context=None):
        '''当联系人改变时，销售订单的地址随之而改变'''
        if not contacts:
            return {}
        contacts = self.pool.get('res.partner.address').browse(
            cr, uid, contacts, context=context)
        return {'value': {
            'province_id': contacts.province_id.id,
            'city_id': contacts.city_id.id,
            'county_id': contacts.county_id.id,
            'street': contacts.detail_street,
            'zip': contacts.zp_code,
            'phone': contacts.phone_number,
            'mobile': contacts.mobile_number,
            'consignee': contacts.contacts,
        }
        }

    def onchange_mobile(self, cr, uid, ids, mobile, context=None):
        # 检查手机号合法
        if mobile:
            p2 = re.compile('\d{11}')
            if not p2.match(mobile):
                raise osv.except_osv(u'警告！', u'手机号码不合规范!')
            return True

    _columns = {
        'contacts': fields.many2one('res.partner.address', u'常用收货地址选择'),
        'province_id': fields.many2one('res.country.state', u'省', domain="[('country_id.name','=','中国')]"),
        'street': fields.char(u'街道地址', size=64),
        'consignee': fields.char(u'收件人', size=64, required=True),
        'city_id': fields.many2one('all.city', u'市'),
        'county_id': fields.many2one('all.country', u'县'),
        'zip': fields.char(u'邮政编码'),
        'phone': fields.char(u'电话号码'),
        'mobile': fields.char(u'手机号码'),
        'department_id': fields.many2one('hr.department', u'销售部门'),
        'is_return': fields.boolean(u'是否退货单', copy=False),
    }

    _defaults = {
        'partner_id': _get_default_partner_id,
    }


class account_invoice(models.Model):
    """
    1.继承发票，添加创建时间
    2.当用户提交订单时就直接生成发票
    """
    _inherit = "account.invoice"

    _columns = {
        'create_date': fields.datetime('Creation datetime', readonly=True),
    }

    # 小于10秒钟则认为刚刚建立的发票，可以自动记账
    def check_invoice_just_create(self, cr, uid, ids, context=None):
        assert len(
            ids) == 1, 'This option should only be used for a single id at a time.'
        invoice = self.browse(cr, uid, ids, context=context)[0]
        diff = datetime.datetime.strptime(fields.datetime.now(), '%Y-%m-%d %H:%M:%S') - \
            datetime.datetime.strptime(
                invoice.create_date, '%Y-%m-%d %H:%M:%S')
        if diff.seconds < 600:
            return True
        else:
            return False


# class account_move_line(osv.osv):
#     _inherit = 'account.move.line'
#
#     def reconcile_partial(self, cr, uid, ids, type='auto', context=None, writeoff_acc_id=False,
#                           writeoff_period_id=False, writeoff_journal_id=False):
#         res_id = True
#         # 系统参数，管理员应该不会去删掉它
#         is_disable_auto_reconcile_id = self.pool.get("ir.config_parameter").search(cr, uid,
#                                                                                    [('key', '=',
#                                                                                      'is_disable_auto_reconcile')],
#                                                                                    context=context)
#         is_disable_auto_reconcile = self.pool.get("ir.config_parameter").browse(
#             cr, uid, is_disable_auto_reconcile_id, context=context)[0].value
#         if not eval(is_disable_auto_reconcile):
#             res_id = super(account_move_line, self).reconcile_partial(cr, uid, ids, type='auto', context=context,
#                                                                       writeoff_acc_id=writeoff_acc_id,
#                                                                       writeoff_period_id=writeoff_period_id,
# #                                                                       writeoff_journal_id=writeoff_journal_id)
#
#         return res_id

class account_voucher(osv.osv):
    _inherit = 'account.voucher'

    def onchange_partner_id(self, cr, uid, ids, partner_id, journal_id, amount, currency_id, ttype, date, context=None):
        is_disable_auto_reconcile_id = self.pool.get("ir.config_parameter").search(cr, uid,
                                                                                   [('key', '=',
                                                                                     'is_disable_auto_reconcile')],
                                                                                   context=context)

        is_disable_auto_reconcile = self.pool.get("ir.config_parameter").browse(
            cr, uid, is_disable_auto_reconcile_id, context=context)[0].value
        res = {}
        if not eval(is_disable_auto_reconcile):
            res = super(account_voucher,self).onchange_partner_id(cr,uid,ids,partner_id,journal_id,
                                                                  amount,currency_id,ttype,date,context=context)
        return res

    def onchange_amount(self, cr, uid, ids, amount, rate, partner_id, journal_id, currency_id, ttype, date,
                        payment_rate_currency_id, company_id, context=None):
        is_disable_auto_reconcile_id = self.pool.get("ir.config_parameter").search(cr, uid,
                                                                                   [('key', '=',
                                                                                     'is_disable_auto_reconcile')],
                                                                                   context=context)
        is_disable_auto_reconcile = self.pool.get("ir.config_parameter").browse(
            cr, uid, is_disable_auto_reconcile_id, context=context)[0].value
        res = {}
        if not eval(is_disable_auto_reconcile):
            res = super(account_voucher, self).onchange_amount(cr, uid, ids, amount, rate, partner_id, journal_id, currency_id, ttype, date,
                        payment_rate_currency_id, company_id, context=context)
        return res

    def onchange_journal(self, cr, uid, ids, journal_id, line_ids, tax_id, partner_id, date, amount, ttype, company_id, context=None):
        is_disable_auto_reconcile_id = self.pool.get("ir.config_parameter").search(cr, uid,
                                                                                   [('key', '=',
                                                                                     'is_disable_auto_reconcile')],
                                                                                   context=context)

        is_disable_auto_reconcile = self.pool.get("ir.config_parameter").browse(
            cr, uid, is_disable_auto_reconcile_id, context=context)[0].value
        res = {}
        if not eval(is_disable_auto_reconcile):
            res = super(account_voucher, self).onchange_journal(cr, uid, ids, journal_id, line_ids, tax_id,
                                                                partner_id, date, amount, ttype, company_id, context=context)
        return res